package de.amaly.wosdemdes.persistence;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import de.amaly.wosdemdes.data.ShowProgressEntry;
import de.amaly.wosdemdes.persistence.DatabaseContract.ShowProgressEntryTable;

/**
 * DAO object for encapsulating database operations related to storing, loading, updating and deleting
 * {@link ShowProgressEntry}s into the embedded SQLite database.
 * 
 * @author Andreas Maly
 * 
 */
public class ShowProgressEntryDAO {

    // Database fields
    private SQLiteDatabase database;
    private final DatabaseHelper dbHelper;
    private final String[] allColumns = { ShowProgressEntryTable._ID, ShowProgressEntryTable.COLUMN_SHOW_NAME,
            ShowProgressEntryTable.COLUMN_SEASON_NUMBER, ShowProgressEntryTable.COLUMN_EPISODE_NUMBER,
            ShowProgressEntryTable.COLUMN_DISC_NUMBER, ShowProgressEntryTable.COLUMN_PROGRESS_COMMENT };


    /**
     * Create the DAO
     * 
     * @param context
     */
    public ShowProgressEntryDAO(Context context) {
        dbHelper = new DatabaseHelper(context);
    }


    /**
     * Open a database connection
     * 
     * @throws SQLException
     */
    public void open() throws SQLException {
        database = dbHelper.getWritableDatabase();
    }


    /**
     * Close the database connection
     */
    public void close() {
        dbHelper.close();
    }


    /**
     * Stores the given {@link ShowProgressEntry} in the database
     * 
     * @param entry
     */
    public void saveShowProgressEntry(ShowProgressEntry entry) {

        // If the entry is not new, but already has a database ID assigned, update it instead
        if (entry.getId() != null) {
            updateShowProgressEntry(entry);

        } else {

            // Open the database
            open();

            // Create a new map of values, where column names are the keys
            ContentValues values = new ContentValues();
            values.put(ShowProgressEntryTable.COLUMN_SHOW_NAME, entry.getShowName());
            values.put(ShowProgressEntryTable.COLUMN_SEASON_NUMBER, entry.getSeasonNumber());
            values.put(ShowProgressEntryTable.COLUMN_EPISODE_NUMBER, entry.getEpisodeNumber());
            values.put(ShowProgressEntryTable.COLUMN_DISC_NUMBER, entry.getDiscNumber());
            values.put(ShowProgressEntryTable.COLUMN_PROGRESS_COMMENT, entry.getProgressComment());

            // Insert the new row, returning the primary key value of the new row
            long newRowId;
            newRowId = database.insert(ShowProgressEntryTable.TABLE_NAME, null, values);
            entry.setId(newRowId);
        }
    }


    public void updateShowProgressEntry(ShowProgressEntry entry) {

        // Open the database
        open();

        // Create a new map of values, where column names are the keys
        ContentValues values = new ContentValues();
        values.put(ShowProgressEntryTable.COLUMN_SHOW_NAME, entry.getShowName());
        values.put(ShowProgressEntryTable.COLUMN_SEASON_NUMBER, entry.getSeasonNumber());
        values.put(ShowProgressEntryTable.COLUMN_EPISODE_NUMBER, entry.getEpisodeNumber());
        values.put(ShowProgressEntryTable.COLUMN_DISC_NUMBER, entry.getDiscNumber());
        values.put(ShowProgressEntryTable.COLUMN_PROGRESS_COMMENT, entry.getProgressComment());

        // Insert the new row, returning the primary key value of the new row
        int updatedRows = database.update(ShowProgressEntryTable.TABLE_NAME, values,
                ShowProgressEntryTable._ID + "= ?", new String[] { entry.getId().toString() });
        if (updatedRows != 1) {
            Log.e("database", "Unexpected update count while trying to update ShowProgressEntry " + entry.getId()
                    + " / " + entry.getShowName());
        }
    }


    public void deleteShowProgressEntry(Long id) {

        // Open the database
        open();

        database.delete(ShowProgressEntryTable.TABLE_NAME, ShowProgressEntryTable._ID + "=?",
                new String[] { String.valueOf(id) });
    }


    /**
     * Returns all {@link ShowProgressEntries} stored in the database
     * 
     * @return
     */
    public List<ShowProgressEntry> getAllShowProgressEntries() {
        final String SORT_ORDER = ShowProgressEntryTable.COLUMN_SHOW_NAME + " ASC";

        List<ShowProgressEntry> entries = new ArrayList<ShowProgressEntry>();
        Cursor cursor = database.query(ShowProgressEntryTable.TABLE_NAME, allColumns, null, null, null, null,
                SORT_ORDER);

        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            ShowProgressEntry entry = cursorToShowProgressEntry(cursor);
            entries.add(entry);
            cursor.moveToNext();
        }

        // make sure to close the cursor
        cursor.close();
        return entries;
    }


    /**
     * Converts a database cursor to a {@link ShowProgressEntry} object.
     * 
     * @param cursor
     * @return
     */
    private ShowProgressEntry cursorToShowProgressEntry(Cursor cursor) {
        ShowProgressEntry entry = new ShowProgressEntry();
        entry.setId(cursor.getLong(0));
        entry.setShowName(cursor.getString(1));
        entry.setSeasonNumber(cursor.getInt(2));
        entry.setEpisodeNumber(cursor.getInt(3));
        entry.setDiscNumber(cursor.getInt(4));
        entry.setProgressComment(cursor.getString(5));
        return entry;
    }
}
